
use crate::models::db_connect::get_conn;
use mysql::prelude::Queryable;
use mysql::{from_row, params};
use rocket::serde::json::Json;
use rocket::Error;
use serde::{Deserialize, Serialize};
use std::string::String;
use chrono::NaiveDateTime;


#[derive(Serialize, Deserialize)]
pub struct TeacherModel {
    
	pub id:	Option<i32>,
	pub name:	Option<String>,
	pub phone:	Option<String>,
	pub tm:	Option<NaiveDateTime>,
}

impl TeacherModel {
    pub fn add(param: Json<TeacherModel>) -> Result<bool, Error> {
        let mut conn = get_conn();
        conn.exec_iter(
            "INSERT INTO teacher(id,name,phone,tm) VALUES (?,?,?,?)",
            (
				param.id.clone().unwrap().to_string(),
				param.name.clone().unwrap().to_string(),
				param.phone.clone().unwrap().to_string(),
				param.tm.clone().unwrap().to_string(),

            ),
        )
        .expect("TODO: panic message");

        Ok(true)
    }

    pub fn query(param: Json<TeacherModel>) -> Result<Vec<TeacherModel>, Error> {
        let mut conn = get_conn();
        let conj = "and";
        let (mut sql_ext, param_values) = TeacherModel::concat_cols_make(param, conj);
        if sql_ext.starts_with(conj) {
            sql_ext = sql_ext[conj.len()..].parse().unwrap()
        }
        let pre_sql: String = String::from("SELECT * FROM teacher where ") + &*sql_ext;
        let stmt = conn.prep(pre_sql);

        let mut teachers = vec![];
        conn.exec_iter(stmt.unwrap(), param_values)
            .unwrap()
            .for_each(|row| {
                let (id,name,phone,tm) = from_row(row.unwrap());
                let query_item = TeacherModel {
						id: Some(id),
						name: Some(name),
						phone: Some(phone),
						tm: Some(tm),
                    };
                teachers.push(query_item);
            });

        Ok(teachers)
    }

    pub fn query_by_pk(id: i32) -> Result<Option<TeacherModel>, Error> {
        let mut conn = get_conn();
        let teacher = conn
            .exec_first(
                "SELECT * FROM teacher WHERE id = :id",
                params! {
                    "id" => id
                },
            )
            .map(|row| {
                row.map(|(id,name,phone,tm)| TeacherModel {
						id: Some(id),
						name: Some(name),
						phone: Some(phone),
						tm: Some(tm),
                })
            });

        Ok(teacher.unwrap())
    }

    pub fn update(param: Json<TeacherModel>) -> Result<bool, Error> {
        let mut conn = get_conn();
        let conj = ",";
        let pk = param.id.clone().unwrap().to_string();
        let (mut sql_ext, mut param_values) = TeacherModel::concat_cols_make(param, conj);
        if sql_ext.starts_with(conj) {
            sql_ext = sql_ext[conj.len()..].parse().unwrap()
        }
        param_values.push(pk);
        let pre_sql: String = String::from("UPDATE teacher SET ") + &*sql_ext + " WHERE id = ? ";
        let stmt = conn.prep(pre_sql);

        conn.exec_iter(stmt.unwrap(), param_values)
            .expect("TODO: panic message");

        Ok(true)
    }

    pub fn delete(id: i32) -> Result<bool, Error> {
        let mut conn = get_conn();
        conn.exec_iter(
            "DELETE FROM teacher WHERE id = :id",
            params! {
                "id" => id
            },
        )
        .unwrap();

        Ok(true)
    }

    fn concat_cols_make(param: Json<TeacherModel>, conj: &str) -> (String, Vec<String>) {
        let mut s = "".to_string();
        let mut v = vec![];
		if param.id.is_some() {
			s += &*(conj.to_owned() + "id = ?");
			v.push(param.id.clone().unwrap().to_string());
		}
		if param.name.is_some() {
			s += &*(conj.to_owned() + "name = ?");
			v.push(param.name.clone().unwrap().to_string());
		}
		if param.phone.is_some() {
			s += &*(conj.to_owned() + "phone = ?");
			v.push(param.phone.clone().unwrap().to_string());
		}
		if param.tm.is_some() {
			s += &*(conj.to_owned() + "tm = ?");
			v.push(param.tm.clone().unwrap().to_string());
		}

        (s, v)
    }
}


